home *** CD-ROM | disk | FTP | other *** search
/ Software of the Month Club 2000 October / Software of the Month - Ultimate Collection Shareware 277.iso / pc / PROGRAMS / UTILITY / WINLINUX / DATA1.CAB / programs_-_include / ASM-SPAR.{_A / PGTABLE.H < prev    next >
C/C++ Source or Header  |  1999-09-17  |  22KB  |  661 lines

  1. /* $Id: pgtable.h,v 1.103 1999/03/28 08:40:04 davem Exp $
  2.  * pgtable.h: SpitFire page table operations.
  3.  *
  4.  * Copyright 1996,1997 David S. Miller (davem@caip.rutgers.edu)
  5.  * Copyright 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
  6.  */
  7.  
  8. #ifndef _SPARC64_PGTABLE_H
  9. #define _SPARC64_PGTABLE_H
  10.  
  11. /* This file contains the functions and defines necessary to modify and use
  12.  * the SpitFire page tables.
  13.  */
  14.  
  15. #ifndef __ASSEMBLY__
  16. #include <linux/mm.h>
  17. #include <linux/pagemap.h>
  18. #endif
  19. #include <asm/spitfire.h>
  20. #include <asm/asi.h>
  21. #include <asm/mmu_context.h>
  22. #include <asm/system.h>
  23.  
  24. #ifndef __ASSEMBLY__
  25. #include <asm/sbus.h>
  26.  
  27. /* Certain architectures need to do special things when pte's
  28.  * within a page table are directly modified.  Thus, the following
  29.  * hook is made available.
  30.  */
  31. #define set_pte(pteptr, pteval) ((*(pteptr)) = (pteval))
  32.  
  33. /* PMD_SHIFT determines the size of the area a second-level page table can map */
  34. #define PMD_SHIFT    (PAGE_SHIFT + (PAGE_SHIFT-3))
  35. #define PMD_SIZE    (1UL << PMD_SHIFT)
  36. #define PMD_MASK    (~(PMD_SIZE-1))
  37.  
  38. /* PGDIR_SHIFT determines what a third-level page table entry can map */
  39. #define PGDIR_SHIFT    (PAGE_SHIFT + (PAGE_SHIFT-3) + (PAGE_SHIFT-2))
  40. #define PGDIR_SIZE    (1UL << PGDIR_SHIFT)
  41. #define PGDIR_MASK    (~(PGDIR_SIZE-1))
  42.  
  43. /* Entries per page directory level. */
  44. #define PTRS_PER_PTE        (1UL << (PAGE_SHIFT-3))
  45.  
  46. /* We the first one in this file, what we export to the kernel
  47.  * is different so we can optimize correctly for 32-bit tasks.
  48.  */
  49. #define REAL_PTRS_PER_PMD    (1UL << (PAGE_SHIFT-2))
  50. #define PTRS_PER_PMD        ((const int)((current->tss.flags & SPARC_FLAG_32BIT) ? \
  51.                  (REAL_PTRS_PER_PMD >> 2) : (REAL_PTRS_PER_PMD)))
  52.  
  53. /* We cannot use the top 16G because VPTE table lives there. */
  54. #define PTRS_PER_PGD        ((1UL << (PAGE_SHIFT-3))-1)
  55.  
  56. /* Kernel has a separate 44bit address space. */
  57. #define USER_PTRS_PER_PGD    ((const int)((current->tss.flags & SPARC_FLAG_32BIT) ? \
  58.                  (1) : (PTRS_PER_PGD)))
  59.  
  60. #define PTE_TABLE_SIZE    0x2000    /* 1024 entries 8 bytes each */
  61. #define PMD_TABLE_SIZE    0x2000    /* 2048 entries 4 bytes each */
  62. #define PGD_TABLE_SIZE    0x1000    /* 1024 entries 4 bytes each */
  63.  
  64. /* the no. of pointers that fit on a page */
  65. #define PTRS_PER_PAGE    (1UL << (PAGE_SHIFT-3))
  66.  
  67. /* NOTE: TLB miss handlers depend heavily upon where this is. */
  68. #define VMALLOC_START        0x0000000140000000UL
  69. #define VMALLOC_VMADDR(x)    ((unsigned long)(x))
  70. #define VMALLOC_END        0x0000000200000000UL
  71.  
  72. #endif /* !(__ASSEMBLY__) */
  73.  
  74. /* SpitFire TTE bits. */
  75. #define _PAGE_VALID    0x8000000000000000    /* Valid TTE                          */
  76. #define _PAGE_R        0x8000000000000000    /* Used to keep ref bit up to date    */
  77. #define _PAGE_SZ4MB    0x6000000000000000    /* 4MB Page                           */
  78. #define _PAGE_SZ512K    0x4000000000000000    /* 512K Page                          */
  79. #define _PAGE_SZ64K    0x2000000000000000    /* 64K Page                           */
  80. #define _PAGE_SZ8K    0x0000000000000000    /* 8K Page                            */
  81. #define _PAGE_NFO    0x1000000000000000    /* No Fault Only                      */
  82. #define _PAGE_IE    0x0800000000000000    /* Invert Endianness                  */
  83. #define _PAGE_SOFT2    0x07FC000000000000    /* Second set of software bits        */
  84. #define _PAGE_DIAG    0x0003FE0000000000    /* Diagnostic TTE bits                */
  85. #define _PAGE_PADDR    0x000001FFFFFFE000    /* Physical Address bits [40:13]      */
  86. #define _PAGE_SOFT    0x0000000000001F80    /* First set of software bits         */
  87. #define _PAGE_L        0x0000000000000040    /* Locked TTE                         */
  88. #define _PAGE_CP    0x0000000000000020    /* Cacheable in Physical Cache        */
  89. #define _PAGE_CV    0x0000000000000010    /* Cacheable in Virtual Cache         */
  90. #define _PAGE_E        0x0000000000000008    /* side-Effect                        */
  91. #define _PAGE_P        0x0000000000000004    /* Privileged Page                    */
  92. #define _PAGE_W        0x0000000000000002    /* Writable                           */
  93. #define _PAGE_G        0x0000000000000001    /* Global                             */
  94.  
  95. /* Here are the SpitFire software bits we use in the TTE's. */
  96. #define _PAGE_MODIFIED    0x0000000000000800    /* Modified Page (ie. dirty)          */
  97. #define _PAGE_ACCESSED    0x0000000000000400    /* Accessed Page (ie. referenced)     */
  98. #define _PAGE_READ    0x0000000000000200    /* Readable SW Bit                    */
  99. #define _PAGE_WRITE    0x0000000000000100    /* Writable SW Bit                    */
  100. #define _PAGE_PRESENT    0x0000000000000080    /* Present Page (ie. not swapped out) */
  101.  
  102. #define _PAGE_CACHE    (_PAGE_CP | _PAGE_CV)
  103.  
  104. #define __DIRTY_BITS    (_PAGE_MODIFIED | _PAGE_WRITE | _PAGE_W)
  105. #define __ACCESS_BITS    (_PAGE_ACCESSED | _PAGE_READ | _PAGE_R)
  106. #define __PRIV_BITS    _PAGE_P
  107.  
  108. #define PAGE_NONE    __pgprot (_PAGE_PRESENT | _PAGE_ACCESSED)
  109.  
  110. /* Don't set the TTE _PAGE_W bit here, else the dirty bit never gets set. */
  111. #define PAGE_SHARED    __pgprot (_PAGE_PRESENT | _PAGE_VALID | _PAGE_CACHE | \
  112.                   __ACCESS_BITS | _PAGE_WRITE)
  113.  
  114. #define PAGE_COPY    __pgprot (_PAGE_PRESENT | _PAGE_VALID | _PAGE_CACHE | \
  115.                   __ACCESS_BITS)
  116.  
  117. #define PAGE_READONLY    __pgprot (_PAGE_PRESENT | _PAGE_VALID | _PAGE_CACHE | \
  118.                   __ACCESS_BITS)
  119.  
  120. #define PAGE_KERNEL    __pgprot (_PAGE_PRESENT | _PAGE_VALID | _PAGE_CACHE | \
  121.                   __PRIV_BITS | __ACCESS_BITS | __DIRTY_BITS)
  122.  
  123. #define PAGE_INVALID    __pgprot (0)
  124.  
  125. #define _PFN_MASK    _PAGE_PADDR
  126.  
  127. #define _PAGE_CHG_MASK    (_PFN_MASK | _PAGE_MODIFIED | _PAGE_ACCESSED | _PAGE_PRESENT)
  128.  
  129. #define pg_iobits (_PAGE_VALID | _PAGE_PRESENT | __DIRTY_BITS | __ACCESS_BITS | _PAGE_E)
  130.  
  131. #define __P000    PAGE_NONE
  132. #define __P001    PAGE_READONLY
  133. #define __P010    PAGE_COPY
  134. #define __P011    PAGE_COPY
  135. #define __P100    PAGE_READONLY
  136. #define __P101    PAGE_READONLY
  137. #define __P110    PAGE_COPY
  138. #define __P111    PAGE_COPY
  139.  
  140. #define __S000    PAGE_NONE
  141. #define __S001    PAGE_READONLY
  142. #define __S010    PAGE_SHARED
  143. #define __S011    PAGE_SHARED
  144. #define __S100    PAGE_READONLY
  145. #define __S101    PAGE_READONLY
  146. #define __S110    PAGE_SHARED
  147. #define __S111    PAGE_SHARED
  148.  
  149. #ifndef __ASSEMBLY__
  150.  
  151. extern pte_t __bad_page(void);
  152.  
  153. #define BAD_PAGE    __bad_page()
  154.  
  155. /* First physical page can be anywhere, the following is needed so that
  156.  * va-->pa and vice versa conversions work properly without performance
  157.  * hit for all __pa()/__va() operations.
  158.  */
  159. extern unsigned long phys_base;
  160. #define ZERO_PAGE    ((unsigned long)__va(phys_base))
  161.  
  162. /* Allocate a block of RAM which is aligned to its size.
  163.  * This procedure can be used until the call to mem_init().
  164.  */
  165. extern void *sparc_init_alloc(unsigned long *kbrk, unsigned long size);
  166.  
  167. /* Cache and TLB flush operations. */
  168.  
  169. /* These are the same regardless of whether this is an SMP kernel or not. */
  170. #define flush_cache_mm(mm)            flushw_user()
  171. #define flush_cache_range(mm, start, end)    flushw_user()
  172. #define flush_cache_page(vma, page)        flushw_user()
  173.  
  174. /* These operations are unnecessary on the SpitFire since D-CACHE is write-through. */
  175. #define flush_icache_range(start, end)        do { } while (0)
  176. #define flush_page_to_ram(page)            do { } while (0)
  177.  
  178. extern void __flush_dcache_range(unsigned long start, unsigned long end);
  179.  
  180. extern void __flush_cache_all(void);
  181.  
  182. extern void __flush_tlb_all(void);
  183. extern void __flush_tlb_mm(unsigned long context, unsigned long r);
  184. extern void __flush_tlb_range(unsigned long context, unsigned long start,
  185.                   unsigned long r, unsigned long end,
  186.                   unsigned long pgsz, unsigned long size);
  187. extern void __flush_tlb_page(unsigned long context, unsigned long page, unsigned long r);
  188.  
  189. #ifndef __SMP__
  190.  
  191. #define flush_cache_all()    __flush_cache_all()
  192. #define flush_tlb_all()        __flush_tlb_all()
  193.  
  194. #define flush_tlb_mm(mm) \
  195. do { if((mm)->context != NO_CONTEXT) \
  196.     __flush_tlb_mm((mm)->context & 0x3ff, SECONDARY_CONTEXT); \
  197. } while(0)
  198.  
  199. #define flush_tlb_range(mm, start, end) \
  200. do { if((mm)->context != NO_CONTEXT) { \
  201.     unsigned long __start = (start)&PAGE_MASK; \
  202.     unsigned long __end = (end)&PAGE_MASK; \
  203.     __flush_tlb_range((mm)->context & 0x3ff, __start, \
  204.               SECONDARY_CONTEXT, __end, PAGE_SIZE, \
  205.               (__end - __start)); \
  206.      } \
  207. } while(0)
  208.  
  209. #define flush_tlb_page(vma, page) \
  210. do { struct mm_struct *__mm = (vma)->vm_mm; \
  211.      if(__mm->context != NO_CONTEXT) \
  212.     __flush_tlb_page(__mm->context & 0x3ff, (page)&PAGE_MASK, \
  213.              SECONDARY_CONTEXT); \
  214. } while(0)
  215.  
  216. #else /* __SMP__ */
  217.  
  218. extern void smp_flush_cache_all(void);
  219. extern void smp_flush_tlb_all(void);
  220. extern void smp_flush_tlb_mm(struct mm_struct *mm);
  221. extern void smp_flush_tlb_range(struct mm_struct *mm, unsigned long start,
  222.                 unsigned long end);
  223. extern void smp_flush_tlb_page(struct mm_struct *mm, unsigned long page);
  224.  
  225. #define flush_cache_all()    smp_flush_cache_all()
  226. #define flush_tlb_all()        smp_flush_tlb_all()
  227.  
  228. extern __inline__ void flush_tlb_mm(struct mm_struct *mm)
  229. {
  230.     if(mm->context != NO_CONTEXT)
  231.         smp_flush_tlb_mm(mm);
  232. }
  233.  
  234. extern __inline__ void flush_tlb_range(struct mm_struct *mm, unsigned long start,
  235.                        unsigned long end)
  236. {
  237.     if(mm->context != NO_CONTEXT)
  238.         smp_flush_tlb_range(mm, start, end);
  239. }
  240.  
  241. extern __inline__ void flush_tlb_page(struct vm_area_struct *vma, unsigned long page)
  242. {
  243.     struct mm_struct *mm = vma->vm_mm;
  244.  
  245.     if(mm->context != NO_CONTEXT)
  246.         smp_flush_tlb_page(mm, page);
  247. }
  248.  
  249. #endif
  250.  
  251. #define mk_pte(page, pgprot)        (__pte(__pa(page) | pgprot_val(pgprot)))
  252. #define mk_pte_phys(physpage, pgprot)    (__pte((physpage) | pgprot_val(pgprot)))
  253. #define pte_modify(_pte, newprot) \
  254.     (pte_val(_pte) = ((pte_val(_pte) & _PAGE_CHG_MASK) | pgprot_val(newprot)))
  255. #define pmd_set(pmdp, ptep)    \
  256.     (pmd_val(*(pmdp)) = (__pa((unsigned long) (ptep)) >> 11UL))
  257. #define pgd_set(pgdp, pmdp)    \
  258.     (pgd_val(*(pgdp)) = (__pa((unsigned long) (pmdp)) >> 11UL))
  259. #define pte_page(pte)   ((unsigned long) __va(((pte_val(pte)&~PAGE_OFFSET)&~(0xfffUL))))
  260. #define pmd_page(pmd)            ((unsigned long) __va((pmd_val(pmd)<<11UL)))
  261. #define pgd_page(pgd)            ((unsigned long) __va((pgd_val(pgd)<<11UL)))
  262. #define pte_none(pte)             (!pte_val(pte))
  263. #define pte_present(pte)        (pte_val(pte) & _PAGE_PRESENT)
  264. #define pte_clear(pte)            (pte_val(*(pte)) = 0UL)
  265. #define pmd_none(pmd)            (!pmd_val(pmd))
  266. #define pmd_bad(pmd)            (0)
  267. #define pmd_present(pmd)        (pmd_val(pmd) != 0UL)
  268. #define pmd_clear(pmdp)            (pmd_val(*(pmdp)) = 0UL)
  269. #define pgd_none(pgd)            (!pgd_val(pgd))
  270. #define pgd_bad(pgd)            (0)
  271. #define pgd_present(pgd)        (pgd_val(pgd) != 0UL)
  272. #define pgd_clear(pgdp)            (pgd_val(*(pgdp)) = 0UL)
  273.  
  274. /* The following only work if pte_present() is true.
  275.  * Undefined behaviour if not..
  276.  */
  277. #define pte_read(pte)        (pte_val(pte) & _PAGE_READ)
  278. #define pte_write(pte)        (pte_val(pte) & _PAGE_WRITE)
  279. #define pte_dirty(pte)        (pte_val(pte) & _PAGE_MODIFIED)
  280. #define pte_young(pte)        (pte_val(pte) & _PAGE_ACCESSED)
  281. #define pte_wrprotect(pte)    (__pte(pte_val(pte) & ~(_PAGE_WRITE|_PAGE_W)))
  282. #define pte_rdprotect(pte)    (__pte(((pte_val(pte)<<1UL)>>1UL) & ~_PAGE_READ))
  283. #define pte_mkclean(pte)    (__pte(pte_val(pte) & ~(_PAGE_MODIFIED|_PAGE_W)))
  284. #define pte_mkold(pte)        (__pte(((pte_val(pte)<<1UL)>>1UL) & ~_PAGE_ACCESSED))
  285.  
  286. /* Be very careful when you change these three, they are delicate. */
  287. static __inline__ pte_t pte_mkyoung(pte_t _pte)
  288. {    if(pte_val(_pte) & _PAGE_READ)
  289.         return __pte(pte_val(_pte)|(_PAGE_ACCESSED|_PAGE_R));
  290.     else
  291.         return __pte(pte_val(_pte)|(_PAGE_ACCESSED));
  292. }
  293.  
  294. static __inline__ pte_t pte_mkwrite(pte_t _pte)
  295. {    if(pte_val(_pte) & _PAGE_MODIFIED)
  296.         return __pte(pte_val(_pte)|(_PAGE_WRITE|_PAGE_W));
  297.     else
  298.         return __pte(pte_val(_pte)|(_PAGE_WRITE));
  299. }
  300.  
  301. static __inline__ pte_t pte_mkdirty(pte_t _pte)
  302. {    if(pte_val(_pte) & _PAGE_WRITE)
  303.         return __pte(pte_val(_pte)|(_PAGE_MODIFIED|_PAGE_W));
  304.     else
  305.         return __pte(pte_val(_pte)|(_PAGE_MODIFIED));
  306. }
  307.  
  308. /* to find an entry in a page-table-directory. */
  309. #define pgd_offset(mm, address) ((mm)->pgd + ((address >> PGDIR_SHIFT) & (PTRS_PER_PGD)))
  310.  
  311. /* to find an entry in a kernel page-table-directory */
  312. #define pgd_offset_k(address) pgd_offset(&init_mm, address)
  313.  
  314. /* Find an entry in the second-level page table.. */
  315. #define pmd_offset(dir, address)    ((pmd_t *) pgd_page(*(dir)) + \
  316.                     ((address >> PMD_SHIFT) & (REAL_PTRS_PER_PMD-1)))
  317.  
  318. /* Find an entry in the third-level page table.. */
  319. #define pte_offset(dir, address)    ((pte_t *) pmd_page(*(dir)) + \
  320.                     ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1)))
  321.  
  322. /* Very stupidly, we used to get new pgd's and pmd's, init their contents
  323.  * to point to the NULL versions of the next level page table, later on
  324.  * completely re-init them the same way, then free them up.  This wasted
  325.  * a lot of work and caused unnecessary memory traffic.  How broken...
  326.  * We fix this by caching them.
  327.  */
  328.  
  329. #ifdef __SMP__
  330. /* Sliiiicck */
  331. #define pgt_quicklists    cpu_data[smp_processor_id()]
  332. #else
  333. extern struct pgtable_cache_struct {
  334.     unsigned long *pgd_cache;
  335.     unsigned long *pte_cache;
  336.     unsigned int pgcache_size;
  337.     unsigned int pgdcache_size;
  338. } pgt_quicklists;
  339. #endif
  340. #define pgd_quicklist        (pgt_quicklists.pgd_cache)
  341. #define pmd_quicklist        ((unsigned long *)0)
  342. #define pte_quicklist        (pgt_quicklists.pte_cache)
  343. #define pgtable_cache_size    (pgt_quicklists.pgcache_size)
  344. #define pgd_cache_size        (pgt_quicklists.pgdcache_size)
  345.  
  346. #ifndef __SMP__
  347.  
  348. extern __inline__ void free_pgd_fast(pgd_t *pgd)
  349. {
  350.     struct page *page = mem_map + MAP_NR(pgd);
  351.  
  352.     if (!page->pprev_hash) {
  353.         (unsigned long *)page->next_hash = pgd_quicklist;
  354.         pgd_quicklist = (unsigned long *)page;
  355.     }
  356.     (unsigned long)page->pprev_hash |=
  357.         (((unsigned long)pgd & (PAGE_SIZE / 2)) ? 2 : 1);
  358.     pgd_cache_size++;
  359. }
  360.  
  361. extern __inline__ pgd_t *get_pgd_fast(void)
  362. {
  363.         struct page *ret;
  364.  
  365.         if ((ret = (struct page *)pgd_quicklist) != NULL) {
  366.                 unsigned long mask = (unsigned long)ret->pprev_hash;
  367.         unsigned long off = 0;
  368.  
  369.         if (mask & 1)
  370.             mask &= ~1;
  371.         else {
  372.             off = PAGE_SIZE / 2;
  373.             mask &= ~2;
  374.         }
  375.         (unsigned long)ret->pprev_hash = mask;
  376.         if (!mask)
  377.             pgd_quicklist = (unsigned long *)ret->next_hash;
  378.                 ret = (struct page *)(page_address(ret) + off);
  379.                 pgd_cache_size--;
  380.         } else {
  381.         ret = (struct page *) __get_free_page(GFP_KERNEL);
  382.         if(ret) {
  383.             struct page *page = mem_map + MAP_NR(ret);
  384.             
  385.             memset(ret, 0, PAGE_SIZE);
  386.             (unsigned long)page->pprev_hash = 2;
  387.             (unsigned long *)page->next_hash = pgd_quicklist;
  388.             pgd_quicklist = (unsigned long *)page;
  389.             pgd_cache_size++;
  390.         }
  391.         }
  392.         return (pgd_t *)ret;
  393. }
  394.  
  395. #else /* __SMP__ */
  396.  
  397. extern __inline__ void free_pgd_fast(pgd_t *pgd)
  398. {
  399.     *(unsigned long *)pgd = (unsigned long) pgd_quicklist;
  400.     pgd_quicklist = (unsigned long *) pgd;
  401.     pgtable_cache_size++;
  402. }
  403.  
  404. extern __inline__ pgd_t *get_pgd_fast(void)
  405. {
  406.     unsigned long *ret;
  407.  
  408.     if((ret = pgd_quicklist) != NULL) {
  409.         pgd_quicklist = (unsigned long *)(*ret);
  410.         ret[0] = 0;
  411.         pgtable_cache_size--;
  412.     } else {
  413.         ret = (unsigned long *) __get_free_page(GFP_KERNEL);
  414.         if(ret)
  415.             memset(ret, 0, PAGE_SIZE);
  416.     }
  417.     return (pgd_t *)ret;
  418. }
  419.  
  420. extern __inline__ void free_pgd_slow(pgd_t *pgd)
  421. {
  422.     free_page((unsigned long)pgd);
  423. }
  424.  
  425. #endif /* __SMP__ */
  426.  
  427. extern pmd_t *get_pmd_slow(pgd_t *pgd, unsigned long address_premasked);
  428.  
  429. extern __inline__ pmd_t *get_pmd_fast(void)
  430. {
  431.     unsigned long *ret;
  432.  
  433.     if((ret = (unsigned long *)pte_quicklist) != NULL) {
  434.         pte_quicklist = (unsigned long *)(*ret);
  435.         ret[0] = 0;
  436.         pgtable_cache_size--;
  437.     }
  438.     return (pmd_t *)ret;
  439. }
  440.  
  441. extern __inline__ void free_pmd_fast(pgd_t *pmd)
  442. {
  443.     *(unsigned long *)pmd = (unsigned long) pte_quicklist;
  444.     pte_quicklist = (unsigned long *) pmd;
  445.     pgtable_cache_size++;
  446. }
  447.  
  448. extern __inline__ void free_pmd_slow(pmd_t *pmd)
  449. {
  450.     free_page((unsigned long)pmd);
  451. }
  452.  
  453. extern pte_t *get_pte_slow(pmd_t *pmd, unsigned long address_preadjusted);
  454.  
  455. extern __inline__ pte_t *get_pte_fast(void)
  456. {
  457.     unsigned long *ret;
  458.  
  459.     if((ret = (unsigned long *)pte_quicklist) != NULL) {
  460.         pte_quicklist = (unsigned long *)(*ret);
  461.         ret[0] = 0;
  462.         pgtable_cache_size--;
  463.     }
  464.     return (pte_t *)ret;
  465. }
  466.  
  467. extern __inline__ void free_pte_fast(pte_t *pte)
  468. {
  469.     *(unsigned long *)pte = (unsigned long) pte_quicklist;
  470.     pte_quicklist = (unsigned long *) pte;
  471.     pgtable_cache_size++;
  472. }
  473.  
  474. extern __inline__ void free_pte_slow(pte_t *pte)
  475. {
  476.     free_page((unsigned long)pte);
  477. }
  478.  
  479. #define pte_free_kernel(pte)    free_pte_fast(pte)
  480. #define pte_free(pte)        free_pte_fast(pte)
  481. #define pmd_free_kernel(pmd)    free_pmd_fast(pmd)
  482. #define pmd_free(pmd)        free_pmd_fast(pmd)
  483. #define pgd_free(pgd)        free_pgd_fast(pgd)
  484. #define pgd_alloc()        get_pgd_fast()
  485.  
  486. extern inline pte_t * pte_alloc(pmd_t *pmd, unsigned long address)
  487. {
  488.     address = (address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1);
  489.     if (pmd_none(*pmd)) {
  490.         pte_t *page = get_pte_fast();
  491.  
  492.         if (!page)
  493.             return get_pte_slow(pmd, address);
  494.         pmd_set(pmd, page);
  495.         return page + address;
  496.     }
  497.     return (pte_t *) pmd_page(*pmd) + address;
  498. }
  499.  
  500. extern inline pmd_t * pmd_alloc(pgd_t *pgd, unsigned long address)
  501. {
  502.     address = (address >> PMD_SHIFT) & (REAL_PTRS_PER_PMD - 1);
  503.     if (pgd_none(*pgd)) {
  504.         pmd_t *page = get_pmd_fast();
  505.  
  506.         if (!page)
  507.             return get_pmd_slow(pgd, address);
  508.         pgd_set(pgd, page);
  509.         return page + address;
  510.     }
  511.     return (pmd_t *) pgd_page(*pgd) + address;
  512. }
  513.  
  514. #define pte_alloc_kernel(pmd, addr)    pte_alloc(pmd, addr)
  515. #define pmd_alloc_kernel(pgd, addr)    pmd_alloc(pgd, addr)
  516.  
  517. extern int do_check_pgt_cache(int, int);
  518.  
  519. /* Nothing to do on sparc64 :) */
  520. #define set_pgdir(address, entry)    do { } while(0)
  521.  
  522. extern pgd_t swapper_pg_dir[1];
  523.  
  524. extern inline void SET_PAGE_DIR(struct task_struct *tsk, pgd_t *pgdir)
  525. {
  526.     if(pgdir != swapper_pg_dir && tsk == current) {
  527.         register unsigned long paddr asm("o5");
  528.  
  529.         paddr = __pa(pgdir);
  530.         __asm__ __volatile__ ("
  531.             rdpr        %%pstate, %%o4
  532.             wrpr        %%o4, %1, %%pstate
  533.             mov        %3, %%g4
  534.             mov        %0, %%g7
  535.             stxa        %%g0, [%%g4] %2
  536.             wrpr        %%o4, 0x0, %%pstate
  537.         " : /* No outputs */
  538.           : "r" (paddr), "i" (PSTATE_MG|PSTATE_IE),
  539.             "i" (ASI_DMMU), "i" (TSB_REG)
  540.           : "o4");
  541.         flush_tlb_mm(current->mm);
  542.     }
  543. }
  544.  
  545. /* Routines for getting a dvma scsi buffer. */
  546. struct mmu_sglist {
  547.     char *addr;
  548.     char *__dont_touch;
  549.     unsigned int len;
  550.     __u32 dvma_addr;
  551. };
  552.  
  553. extern __u32 mmu_get_scsi_one(char *, unsigned long, struct linux_sbus *sbus);
  554. extern void  mmu_get_scsi_sgl(struct mmu_sglist *, int, struct linux_sbus *sbus);
  555.  
  556. extern void mmu_release_scsi_one(u32 vaddr, unsigned long len,
  557.                  struct linux_sbus *sbus);
  558. extern void mmu_release_scsi_sgl(struct mmu_sglist *sg, int sz, struct linux_sbus *sbus);
  559.  
  560. #define NEED_DMA_SYNCHRONIZATION
  561. #define mmu_sync_dma(dma_addr, len, sbus_instance)    \
  562.     mmu_release_scsi_one((dma_addr), (len), (sbus_instance))
  563.  
  564. /* These do nothing with the way I have things setup. */
  565. #define mmu_lockarea(vaddr, len)        (vaddr)
  566. #define mmu_unlockarea(vaddr, len)        do { } while(0)
  567.  
  568. /* There used to be some funny code here which tried to guess which
  569.  * TLB wanted the mapping, that wasn't accurate enough to justify it's
  570.  * existance.  The real way to do that is to have each TLB miss handler
  571.  * pass in a distinct code to do_sparc64_fault() and do it more accurately
  572.  * there.
  573.  *
  574.  * What we do need to handle here is prevent I-cache corruption.  The
  575.  * deal is that the I-cache snoops stores from other CPUs and all DMA
  576.  * activity, however stores from the local processor are not snooped.
  577.  * The dynamic linker and our signal handler mechanism take care of
  578.  * the cases where they write into instruction space, but when a page
  579.  * is copied in the kernel and then executed in user-space is not handled
  580.  * right.  This leads to corruptions if things are "just right", consider
  581.  * the following scenerio:
  582.  * 1) Process 1 frees up a page that was used for the PLT of libc in
  583.  *    it's address space.
  584.  * 2) Process 2 writes into a page in the PLT of libc for the first
  585.  *    time.  do_wp_page() copies the page locally, the local I-cache of
  586.  *    the processor does not notice the writes during the page copy.
  587.  *    The new page used just so happens to be the one just freed in #1.
  588.  * 3) After the PLT write, later the cpu calls into an unresolved PLT
  589.  *    entry, the CPU executes old instructions from process 1's PLT
  590.  *    table.
  591.  * 4) Splat.
  592.  */
  593. extern void flush_icache_page(unsigned long phys_page);
  594. #define update_mmu_cache(__vma, __address, _pte) \
  595. do { \
  596.     unsigned short __flags = ((__vma)->vm_flags); \
  597.     if ((__flags & VM_EXEC) != 0 && \
  598.         ((pte_val(_pte) & (_PAGE_PRESENT | _PAGE_WRITE | _PAGE_MODIFIED)) == \
  599.          (_PAGE_PRESENT | _PAGE_WRITE | _PAGE_MODIFIED))) { \
  600.         flush_icache_page(pte_page(_pte) - page_offset); \
  601.     } \
  602. } while(0)
  603.  
  604. /* Make a non-present pseudo-TTE. */
  605. extern inline pte_t mk_swap_pte(unsigned long type, unsigned long offset)
  606. { pte_t pte; pte_val(pte) = (type<<PAGE_SHIFT)|(offset<<(PAGE_SHIFT+8)); return pte; }
  607.  
  608. extern inline pte_t mk_pte_io(unsigned long page, pgprot_t prot, int space)
  609. {
  610.     pte_t pte;
  611.     pte_val(pte) = ((page) | pgprot_val(prot) | _PAGE_E) & ~(unsigned long)_PAGE_CACHE;
  612.     pte_val(pte) |= (((unsigned long)space) << 32);
  613.     return pte;
  614. }
  615.  
  616. #define SWP_TYPE(entry)        (((entry>>PAGE_SHIFT) & 0xff))
  617. #define SWP_OFFSET(entry)    ((entry) >> (PAGE_SHIFT+8))
  618. #define SWP_ENTRY(type,offset)    pte_val(mk_swap_pte((type),(offset)))
  619.  
  620. extern __inline__ unsigned long
  621. sun4u_get_pte (unsigned long addr)
  622. {
  623.     pgd_t *pgdp;
  624.     pmd_t *pmdp;
  625.     pte_t *ptep;
  626.  
  627.     if (addr >= PAGE_OFFSET)
  628.         return addr & _PAGE_PADDR;
  629.     pgdp = pgd_offset_k (addr);
  630.     pmdp = pmd_offset (pgdp, addr);
  631.     ptep = pte_offset (pmdp, addr);
  632.     return pte_val (*ptep) & _PAGE_PADDR;
  633. }
  634.  
  635. extern __inline__ unsigned long
  636. __get_phys (unsigned long addr)
  637. {
  638.     return sun4u_get_pte (addr);
  639. }
  640.  
  641. extern __inline__ int
  642. __get_iospace (unsigned long addr)
  643. {
  644.     return ((sun4u_get_pte (addr) & 0xf0000000) >> 28);
  645. }
  646.  
  647. extern void * module_map (unsigned long size);
  648. extern void module_unmap (void *addr);
  649. extern unsigned long *sparc64_valid_addr_bitmap;
  650.  
  651. /* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
  652. #define PageSkip(page)        (test_bit(PG_skip, &(page)->flags))
  653. #define kern_addr_valid(addr)    (test_bit(__pa((unsigned long)(addr))>>22, sparc64_valid_addr_bitmap))
  654.  
  655. extern int io_remap_page_range(unsigned long from, unsigned long offset,
  656.                    unsigned long size, pgprot_t prot, int space);
  657.  
  658. #endif /* !(__ASSEMBLY__) */
  659.  
  660. #endif /* !(_SPARC64_PGTABLE_H) */
  661.